#ifndef MANIPULADORVECTOR_H_
#define MANIPULADORVECTOR_H_
#include <vector>
/*
 * Clase encargada de realizar metodos sobre vectores cuyos elementos son template.
 * 
 * */
class ManipuladorVector
{
public:

    ManipuladorVector()
    {}

    /*
     * Se agrega un elemento de tipo T en un vector de T, en la posicion indicada en el parametro 
     * posicion. 
     * */
    template <typename T >
    static void agregarClaveVector(const T& clave, int posicion, std::vector< T > &vectorClaves )
    {
        typename std::vector<T>::iterator it;
        it= vectorClaves.begin();
        for (int i = 0; i < posicion; ++i)
        {
            ++it;
        }
        if(vectorClaves.size()!=0)
            vectorClaves.insert(it , clave );
        else
            vectorClaves.push_back(clave);
    }

    template <typename T>
    static void borrarClaveVector( int posicion, std::vector<T>& vectorClaves)
    {
        for (unsigned j = posicion; j < (vectorClaves.size() - 1); j++)
        {
            /*piso los valores*/
            vectorClaves[j] = vectorClaves[j+ 1];
        }
        /*nuevo tamaÃ±o de vector*/
        vectorClaves.pop_back();

    }

    /*
     * De dos vectores se pasan todas las claves a uno de los vectores (el segundo)
     * pre: el primer vector debe tener claves menores a las claves del segundo.
     * El primer vector quedara vacio.
     * */
    template <typename T>
    static void dosAUno(std::vector< T>& claves1, std::vector< T>& claves2)
    {
        unsigned  cantTotalClaves = claves1.size() + claves2.size();
        std::vector< T> auxiliar;

        T t;
        unsigned i;
        for (i =0;i< claves1.size(); i++)
        {
            /*copio el vector1 a auxiliar*/
            t = claves1[i];
            auxiliar.push_back(t);
        }
        for (i =0;i< claves2.size(); i++)
        {
            /*copio el vector2 a auxiliar*/
            t = claves2[i];
            auxiliar.push_back(t);
        }

        /*los vacio a los vectores*/
        claves1.clear();
        claves2.clear();

        /*les cargo de a mitad*/
        for (i =0; i<cantTotalClaves; i++ )
        {
            t = auxiliar[i];
            claves2.push_back(t);

        }
    }

    /*
     * Dos vectores se reparten la claves de manera de que queden en ambos la misma o una
     * diferencia de una clave. Quedando las claves de manera ordenada.
     * pre: el primer vector debe tener claves menores a las claves del segundo.
     * */
    template <typename T>
    static void balancearDos(std::vector< T>& claves1, std::vector< T>& claves2)
    {/*el claves1 tiene mas elementos q el clave 2*/
        unsigned  cantTotalClaves = claves1.size() + claves2.size();
        unsigned mitad= (int)(cantTotalClaves / 2);
        unsigned resto = (cantTotalClaves % 2);
        std::vector< T> auxiliar;

        T t;
        unsigned i;
        for (i =0;i< claves1.size(); i++)
        {
            /*copio el vector1 a auxiliar*/
            t = claves1[i];
            auxiliar.push_back(t);
        }
        for (i =0;i< claves2.size(); i++)
        {
            /*copio el vector2 a auxiliar*/
            t = claves2[i];
            auxiliar.push_back(t);
        }

        /*los vacio a los vectores*/
        claves1.clear();
        claves2.clear();

        /*les cargo de a mitad*/
        for (i =0; i<(mitad+resto); i++ )
        {
            t = auxiliar[i];
            claves1.push_back(t);

        }
        for (i =(mitad+resto); i<(cantTotalClaves); i++ )
        {
            t = auxiliar[i];
            claves2.push_back(t);

        }


    }


    template <typename T>
    static void balancearVectores(std::vector<T>& claves1, std::vector<T>& claves2)
    {

        balancearDos(claves1, claves2);

    }

    /*Pre: los vectores vienen ordenandos, es decir las claves de claves1 son menores que las de claves2, etc...
     * Por lo general este método se llama con clave1 y clave2 llenos y clave3 vacío (el nuevo nodo)
     * Los tres vectores se reparten la claves de manera de que queden en ambos la misma o una
     * diferencia de una clave. Quedando las claves de manera ordenada.
     * */
    template <typename T>
    static void balancearTres(std::vector< T>& claves1, std::vector< T>& claves2, std::vector< T>& claves3)
    {
        /*el claves1 tiene mas elementos q el clave 2*/
        unsigned int cantTotalClaves = claves1.size() + claves2.size()+ claves3.size();
        unsigned tercio= (unsigned)(cantTotalClaves / 3);
        unsigned resto = (cantTotalClaves % 3);
        std::vector< T> auxiliar;

        T t;
        unsigned int i;
        for (i =0;i< claves1.size(); i++)
        {
            /*copio el vector1 a auxiliar*/
            t = claves1[i];
            auxiliar.push_back(t);
        }
        for (i =0;i< claves2.size(); i++)
        {
            /*copio el vector2 a auxiliar*/
            t = claves2[i];
            auxiliar.push_back(t);
        }
        for (i =0;i< claves3.size(); i++)
        {
            /*copio el vector3 a auxiliar*/
            t = claves3[i];
            auxiliar.push_back(t);
        }
        int r2= (resto == 2);
        int r1= (resto == 1);

        /*los vacio a los 3 vectores*/
        claves1.clear();
        claves2.clear();
        claves3.clear();

        /*les cargo de a tercios*/
        for (i =0; i<(tercio+r1+r2); i++ )
        {
            t = auxiliar[i];
            claves1.push_back(t);

        }
        for (i =(tercio+r2+r1); i<(2*(tercio+r2)+r1); i++ )
        {
            t = auxiliar[i];
            claves2.push_back(t);

        }
        for (i =(2*(tercio+r2)+r1); i<cantTotalClaves; i++ )
        {
            t = auxiliar[i];
            claves3.push_back(t);

        }

    }

    /*Se deja al vector del medio sin claves, y se reparten estre los dos de los costados las caves de los tres*/
    /*Pre: los vectores vienen ordenandos, es decir las claves de claves1 son menores que las de claves2, etc... */
    template <typename T>
    static void balancearTresADos(std::vector< T>& claves1, std::vector< T>& claves2, std::vector< T>& claves3)
    {
        
        unsigned int cantTotalClaves = claves1.size() + claves2.size()+ claves3.size();

        unsigned mitad= (unsigned)(cantTotalClaves / 2);
        unsigned resto = (cantTotalClaves % 2);

        std::vector< T> auxiliar;

        T t;
        unsigned int i;
        for (i =0;i< claves1.size(); i++)
        {
            /*copio el vector1 a auxiliar*/
            t = claves1[i];
            auxiliar.push_back(t);
        }
        for (i =0;i< claves2.size(); i++)
        {
            /*copio el vector2 a auxiliar*/
            t = claves2[i];
            auxiliar.push_back(t);
        }
        for (i =0;i< claves3.size(); i++)
        {
            /*copio el vector3 a auxiliar*/
            t = claves3[i];
            auxiliar.push_back(t);
        }
        /*los vacio a los 3 vectores*/
        while(claves1.size() != 0)
        {
            claves1.pop_back();
        }
        while(claves2.size() != 0)
        {
            claves2.pop_back();
        }
        while(claves3.size() != 0)
        {
            claves3.pop_back();
        }
        /*les cargo al primero y al ulitmo las claves*/
        for (i =0; i<(mitad+resto); i++ )
        {
            t = auxiliar[i];
            claves1.push_back(t);

        }
        for (i =(mitad+resto); i<cantTotalClaves; i++ )
        {
            t = auxiliar[i];
            claves3.push_back(t);

        }

    }


};

#endif /*MANIPULADORVECTOR_H_*/
